#include "Users.h"
#include "UserEditing.h"
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>

#include "OverlayManagement.h"
#include "Waiting.h"
#include "Input.h"
#include "md5wait.h"
#ifdef __CBM__
#include <cbm.h>
#elif defined(__APPLE2ENH__)
#include <apple2enh.h>
#elif defined(__ATARI__)
#include <atari.h>
#endif

#pragma code-name("USERCODE")
#pragma rodata-name("USERCODE")
#pragma data-name("USERDATA")
//#pragma bss-name("USERBSS")

char buffer[81];

bool getHashedValue(unsigned char *field)
{
	static bool abort;
	static char password[31];

	abort = false;

	memset(buffer, 0, 31);

	while(!abort && strlen(buffer) < 5)
	{
		textcolor(COLOR_YELLOW);
		cputsxy(1, 19, "Enter : ");
		inputString(IO_ALPHA_NUMERIC, buffer, 30, true);

		abort = buffer[0] == '\0';
	}

	if(!abort)
	{
		strcpy(password, buffer);

		memset(buffer, 0, 31);

		while(!abort && strlen(buffer) < 5)
		{
			textcolor(COLOR_YELLOW);
			cputsxy(1, 20, "Verify: ");
			inputString(IO_ALPHA_NUMERIC, buffer, 30, true);

			abort = buffer[0] == '\0';
		}

		if(!abort)
		{
			if(strcmp(password, buffer) != 0)
			{
				textcolor(COLOR_RED);
				cputsxy(1, 22, "Passwords do not match.  Hit any key.");

				abort = true;
			}
			else
			{
				memcpy(field, WaitMDString(password), 16);
				textcolor(COLOR_GREEN);
				cputsxy(1, 22, "Password set.  Hit any key.");

				abort = false;
			}

			cgetc();
		}
	}

	return !abort;
}

bool changeChallengeAnswer(unsigned char *field)
{
	textcolor(COLOR_YELLOW);
	cputsxy(1, 16, "Enter a new challenge answer which must\n\r be at least 5 characters long.");

	return getHashedValue(field);
}


bool changePassword(unsigned char *field)
{
	textcolor(COLOR_YELLOW);
	cputsxy(1, 16, "Enter a new password which must be\n\r at least 5 characters long.");

	return getHashedValue(field);
}

void selectUserToEdit(void)
{
	bool paint;
	static char c;

	clrscr();
	textcolor(COLOR_YELLOW);

	cputcxy(1, 1, CH_ULCORNER);
	chlinexy(2, 1, 5);
	cputcxy(7, 1, CH_URCORNER);
	cputcxy(1, 2, CH_VLINE);
	cputcxy(7, 2, CH_VLINE);
	cputcxy(1, 3, CH_LTEE);
	chlinexy(2, 3, 5);
	cputcxy(7, 3, CH_RTEE);
	cputcxy(1, 4, CH_VLINE);
	cputcxy(7, 4, CH_VLINE);
	cputcxy(1, 5, CH_LLCORNER);
	chlinexy(2, 5, 5);
	cputcxy(7, 5, CH_LRCORNER);

	cputcxy(21, 1, CH_ULCORNER);
	chlinexy(22, 1, 13);
	cputcxy(35, 1, CH_URCORNER);
	cputcxy(21, 2, CH_VLINE);
	cputcxy(35, 2, CH_VLINE);
	cputcxy(21, 3, CH_LTEE);
	chlinexy(22, 3, 13);
	cputcxy(35, 3, CH_RTEE);
	cputcxy(21, 4, CH_VLINE);
	cputcxy(35, 4, CH_VLINE);
	cputcxy(21, 5, CH_LLCORNER);
	chlinexy(22, 5, 13);
	cputcxy(35, 5, CH_LRCORNER);

	textcolor(COLOR_WHITE);

	cputsxy(2, 2, "USER#");
	cputsxy(22, 2, "USERNAME");

	textcolor(COLOR_GREEN);
	gotoxy(2, 4);


	memset(buffer, 0, 81);

	inputString(IO_NUMERIC, buffer, 4, false);

	if(strlen(buffer) > 0 && atoi(buffer) > 0)
	{
		editUserOffline(atoi(buffer));
		selectUserToEdit();
	}
	else
	{
		cclearxy(2, 4, 5);
		gotoxy(22, 4);
		memset(buffer, 0, 81);
		inputString(IO_ALPHA_NUMERIC, buffer, 12, false);

		if(strlen(buffer) > 0)
		{
			c = loadUserByName(buffer, &_currentUser);
			if(c > 0)
			{
				editUserOffline(c);
			}
			else
			{
				cputsxy(1, 20, "Unknown user. Hit any key.");
				cgetc();
			}
			selectUserToEdit();
		}
		else
		{
			textcolor(COLOR_YELLOW);
			cputsxy(1, 20, "Do you wish to create a new user?");
			textcolor(COLOR_WHITE);

			c = getYesNo();

			textcolor(COLOR_WHITE);
			if(c == 1)
			{
				cputs("Yes");
				editUserOffline(createNewUser());
				selectUserToEdit();
			}
			else
			{
				cputs("No");
				return;
			}
		}
	}
}

int createNewUser(void)
{
	initUser();

	_currentUser.usernumber = getNextUserNumber();

	return saveUser(&_currentUser);
}

void writeUserRecordToScreen(void)
{
	textcolor(COLOR_WHITE);

	itoa(_currentUser.usernumber, buffer, 10);
	cputsxy(17, 1, buffer);
	if(_currentUser.isDeleted) cputsxy(27, 1, "DELETED");
	cputsxy(17, 2, _currentUser.username);
	cputsxy(17, 3, _currentUser.decorated_username);

	textcolor(COLOR_WHITE);
	cputsxy(17, 4, _currentUser.firstName);
	cputsxy(17, 5, _currentUser.lastName);
	cputsxy(17, 6, _currentUser.phone);
	//uitoa(_currentUser.securityLevel, buffer, 10);
	sprintf(buffer, "%u", _currentUser.securityLevel);
	cputsxy(17, 7, buffer);
	sprintf(buffer, "%u", _currentUser.accessGroups);
	cputsxy(17, 8, buffer);
}

void writeUserFormToScreen()
{
	textcolor(COLOR_YELLOW);

	cputsxy(1, 1, "   User Number:");
	cputsxy(1, 2, "1: User Name  :");
	cputsxy(1, 3, "2: Alias      :");
	cputsxy(1, 4, "3: First Name :");
	cputsxy(1, 5, "4: Last Name  :");
	cputsxy(1, 6, "5: Phone      :");
	cputsxy(1, 7, "6: Sec. Level :");
	cputsxy(1, 8, "7: Access Grps:");
	cputsxy(1, 10, "P: Set Password");
	cputsxy(1, 11, "U: Set Security Answer");
	cputsxy(1, 12, "A: Abort Changes");
	cputsxy(1, 13, "S: Save Changes");
	cputsxy(1, 14, "D: Delete User");
	cputsxy(1, 15, "< / > Prev / Next");
}

void editUserOffline(int userNumber)
{
	static char c;

	clrscr();
	writeUserFormToScreen();
	if(loadUserByNumber(userNumber, &_currentUser) == userNumber)
	{
		writeUserRecordToScreen();

		c = 0;
		while(c != 'A' && c != 'a' && c != 'S' && c != 's' &&
			c != 'P' && c != 'p' && c != 'U' && c != 'u' &&
			c != 'D' && c != 'd' && c !='<' && c != '>')
		{
			if(kbhit())
			{
				c = cgetc();

				switch(c)
				{
				case '1':
					gotoxy(17, 2);
					inputString(IO_ALPHA_NUMERIC, _currentUser.username, 11, false);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '2':
					gotoxy(17, 3);
					inputString(IO_ALPHA_NUMERIC, _currentUser.decorated_username, 20, false);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '3':
					gotoxy(17, 4);
					inputString(IO_ALPHA_NUMERIC, _currentUser.firstName, 20, false);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '4':
					gotoxy(17, 5);
					inputString(IO_ALPHA_NUMERIC, _currentUser.lastName, 20, false);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '5':
					gotoxy(17, 6);
					inputString(IO_ALPHA_NUMERIC, _currentUser.phone, 15, false);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '6':
					gotoxy(17, 7);
					memset(buffer, 0, 81);
					sprintf(buffer, "%u", _currentUser.securityLevel);
					inputString(IO_NUMERIC, buffer, 2, false);
					_currentUser.securityLevel = atoi(buffer);
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;

				case '7':
					gotoxy(17, 8);
					memset(buffer, 0, 81);
					sprintf(buffer, "%u", _currentUser.accessGroups);
					inputString(IO_NUMERIC, buffer, 5, false);
					if(atol(buffer) > 65535) 
					{
						_currentUser.accessGroups = 65535;
					}
					else
					{
						_currentUser.accessGroups = atoi(buffer);
					}
					clrscr();
					writeUserFormToScreen();
					writeUserRecordToScreen();
					break;
				}
			}
		}

		if(c == 'P' || c == 'p')
		{
			if(changePassword(_currentUser.passwordHash))
			{
				if(saveUser(&_currentUser) == -1)
				{
					textcolor(COLOR_RED);
					cputsxy(1, 22, "Duplicate username.  Hit any key.");
				}
				else
				{
					textcolor(COLOR_YELLOW);
					cputsxy(1, 22, "Saved User.  Hit any key.");
				}
				cgetc();
			}
			editUserOffline(userNumber);
		}
		else if(c == '<')
		{
			if(_currentUser.usernumber > 1)
			{
				editUserOffline(_currentUser.usernumber - 1);
			}
		}
		else if(c == '>')
		{
			editUserOffline(_currentUser.usernumber + 1);
		}
		else if(c == 'U' || c == 'u')
		{
			if(changeChallengeAnswer(_currentUser.challengeAnswer))
			{
				if(saveUser(&_currentUser) == -1)
				{
					textcolor(COLOR_RED);
					cputsxy(1, 22, "Duplicate username.  Hit any key.");
				}
				else
				{
					textcolor(COLOR_YELLOW);
					cputsxy(1, 22, "Saved User.  Hit any key.");
				}
				cgetc();
			}
			editUserOffline(userNumber);
		}
		else if(c == 'D' || c == 'd')
		{
			if(_currentUser.isDeleted == 0)
			{
				_currentUser.isDeleted = 1;
			}
			else
			{
				_currentUser.isDeleted = 0;
			}

			if(saveUser(&_currentUser) == -1)
			{
				textcolor(COLOR_RED);
				cputsxy(1, 22, "Duplicate username.  Hit any key.");
			}
			else
			{
				textcolor(COLOR_YELLOW);
				cputsxy(1, 22, "Saved User.  Hit any key.");
			}
			cgetc();

			editUserOffline(userNumber);
		}
		else if(c == 'S' || c == 's')
		{
			if(saveUser(&_currentUser) == -1)
			{
				textcolor(COLOR_RED);
				cputsxy(1, 22, "Duplicate username.  Hit any key.");
			}
			else
			{
				textcolor(COLOR_YELLOW);
				cputsxy(1, 22, "Saved User.  Hit any key.");
			}
			cgetc();
		}
		else
		{
			textcolor(COLOR_YELLOW);
			cputsxy(1, 22, "Abort? [Y/N] ");
			textcolor(COLOR_WHITE);
			switch((c = getYesNo()))
			{
			case 1:
				cputs("Yes");
				break;
			case 2:
				cputs("No");
				break;
			}

			if(c == 2) editUserOffline(userNumber);
		}
	}
	else
	{
		textcolor(COLOR_RED);
		cputsxy(1, 22, "User not found. Hit any key.");
		cgetc();
	}

	//loadOverlay("bbs.wait", waitForCall);
	return;
}